package com.mg.plugin.agrometeorology.common;

import com.mg.plugin.agrometeorology.entity.StationData;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author xiaolu
 * @date 2018/7/18 上午11:24
 */
public class ChillingDamageCalculator {
    private final static String CORN_EMERGE_DATE = "05-16";
    private final static String CORN_SEVEN_LEAF_DATE = "06-10";
    private final static String CORN_TASSELING_STAGE_DATE = "07-23";
    private final static String CORN_MILKY_RIPENESS_DATE = "08-22";
    private final static String RICE_TRANSPLANT_DATE = "05-25";
    private final static String RICE_TILLER_DATE = "06-20";
    private final static String RICE_BEFORE_EAR_DATE = "07-17";
    private final static String RICE_EAR_DATE = "08-07";
    private final static String RICE_AFTER_EAR_DATE = "08-17";
    private final static String RICE_RIPE_DATE = "09-19";

    public static Collection<? extends String> calcCornChillingDamage(Map<String, List<StationData>> newStationDataMap, Date now) throws ParseException {
        List<String> result = new ArrayList<String>();
        assistHeader(result);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        SimpleDateFormat sdfYear = new SimpleDateFormat("yyyy");

        for (String stationId : newStationDataMap.keySet()) {
            List<StationData> stationDataList = newStationDataMap.get(stationId);
            if (null == stationDataList || stationDataList.size() <= 0) {
                continue;
            }
            String year = sdfYear.format(now);
            stationDataList = sortByDate(sdf, stationDataList);
            double level = calcSingleCornChillingDamage(sdf, stationDataList, year);
            result.add(stationId + "," + sdf.format(now) + "," + level);
        }
        return result;
    }

    /**
     * calcSingleCornChillingDamage
     *
     * @param sdf
     * @param stationDataList
     * @param year
     * @return
     * @throws ParseException
     */
    private static double calcSingleCornChillingDamage(SimpleDateFormat sdf, List<StationData> stationDataList, String year) throws ParseException {
        double ha = 0;
        double score = 0;
        Date now;
        for (StationData stationData : stationDataList) {
            now = sdf.parse(stationData.getDate());
            if (now.after(sdf.parse(year + "-" + CORN_EMERGE_DATE))) {
                if (sdf.parse(stationData.getDate()).before(sdf.parse(year + "-" + CORN_MILKY_RIPENESS_DATE))) {
                    ha += stationData.getTemp() - stationData.getOldTemp();
                }
            }
            if (now.before(sdf.parse(year + "-" + CORN_SEVEN_LEAF_DATE))) {
                if (ha < -35) {
                    score = 55;
                }
            } else if (now.before(sdf.parse(year + "-" + CORN_TASSELING_STAGE_DATE))) {
                if (ha < -45) {
                    score = 70;
                }
            } else if (now.before(sdf.parse(year + "-" + CORN_MILKY_RIPENESS_DATE))) {
                if (ha < -50) {
                    score = 78;
                }
            }
        }

        return score;
    }


    public static Collection<? extends String> calcRiceChillingDamage(Map<String, List<StationData>> newStationDataMap, Date now) throws ParseException {
        List<String> result = new ArrayList<String>();
        String head = "stationId,date,moderateLevel,seriousLevel,obstacleLevel";
        String type = "String,String,Double,Double,Double";
        result.add(head);
        result.add(type);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        SimpleDateFormat sdfYear = new SimpleDateFormat("yyyy");

        for (String stationId : newStationDataMap.keySet()) {
            List<StationData> stationDataList = newStationDataMap.get(stationId);
            if (null == stationDataList || stationDataList.size() <= 0) {
                continue;
            }
            String year = sdfYear.format(now);
            stationDataList = sortByDate(sdf, stationDataList);
            Double[] value = calModerateLevel(sdf, stationDataList, year);
            double moderateLevel = value[0];
            double seriousLevel = value[1];
            double obstacleLevel = calObstacleLevel(sdf, stationDataList, year);
            result.add(stationId + "," + sdf.format(now) + "," + moderateLevel + "," + seriousLevel + "," + obstacleLevel);
        }
        return result;
    }

    private static double calObstacleLevel(SimpleDateFormat sdf, List<StationData> stationDataList, String year) throws ParseException {
        double ha16 = 0;
        double ha17 = 0;
        double moderateScore = 0;
        Date now;
        for (StationData stationData : stationDataList) {
            now = sdf.parse(stationData.getDate());
            if (now.after(sdf.parse(year + "-" + RICE_BEFORE_EAR_DATE))) {
                if (sdf.parse(stationData.getDate()).before(sdf.parse(year + "-" + RICE_EAR_DATE))) {
                    if (stationData.getTemp() < 17) {
                        ha17++;
                    } else {
                        if (ha17 >= 4) {
                            moderateScore = moderateScore > 3 ? moderateScore : 3;
                        }
                        if (ha17 >= 3) {
                            moderateScore = moderateScore > 2 ? moderateScore : 2;
                        }
                        if (ha17 >= 2) {
                            moderateScore = moderateScore > 1 ? moderateScore : 1;
                        }
                    }
                    if (stationData.getTemp() < 16) {
                        ha16++;
                    } else {
                        if (ha16 >= 3) {
                            moderateScore = moderateScore > 3 ? moderateScore : 3;
                        }
                        if (ha16 >= 2) {
                            moderateScore = moderateScore > 2 ? moderateScore : 2;
                        }
                    }
                }
            } else if (now.after(sdf.parse(year + "-" + RICE_EAR_DATE))) {
                if (sdf.parse(stationData.getDate()).before(sdf.parse(year + "-" + RICE_AFTER_EAR_DATE))) {
                    if (stationData.getTemp() < 19) {
                        ha17++;
                    } else {
                        if (ha17 >= 4) {
                            moderateScore = moderateScore > 3 ? moderateScore : 3;
                        }
                        if (ha17 >= 3) {
                            moderateScore = moderateScore > 2 ? moderateScore : 2;
                        }
                        if (ha17 >= 2) {
                            moderateScore = moderateScore > 1 ? moderateScore : 1;
                        }
                    }
                    if (stationData.getTemp() < 18) {
                        ha16++;
                    } else {
                        if (ha16 >= 3) {
                            moderateScore = moderateScore > 3 ? moderateScore : 3;
                        }
                        if (ha16 >= 2) {
                            moderateScore = moderateScore > 2 ? moderateScore : 2;
                        }
                    }
                }
            }

        }

        return moderateScore;
    }

    private static Double[] calModerateLevel(SimpleDateFormat sdf, List<StationData> stationDataList, String year) throws ParseException {
        double ha = 0;
        double moderateScore = 0;
        double seriousScore = 0;
        Date now;
        for (StationData stationData : stationDataList) {
            now = sdf.parse(stationData.getDate());
            if (now.after(sdf.parse(year + "-" + RICE_TRANSPLANT_DATE))) {
                if (sdf.parse(stationData.getDate()).before(sdf.parse(year + "-" + RICE_RIPE_DATE))) {
                    ha += stationData.getTemp() - stationData.getOldTemp();
                }
            }
            if (now.before(sdf.parse(year + "-" + RICE_TILLER_DATE))) {
                if (ha < -43) {
                    moderateScore = 55;
                }
                if (ha < -55) {
                    seriousScore = 52;
                }
            } else if (now.before(sdf.parse(year + "-" + RICE_EAR_DATE))) {
                if (ha < -55) {
                    moderateScore = 85;
                }
                if (ha < -70) {
                    seriousScore = 85;
                }
            } else if (now.before(sdf.parse(year + "-" + RICE_RIPE_DATE))) {
                if (ha < -65) {
                    moderateScore = 97;
                }
                if (ha < -80) {
                    seriousScore = 97;
                }
            }
        }

        return new Double[]{moderateScore, seriousScore};
    }


    /**
     * 站点数据按时间排序
     *
     * @param sdf             SimpleDateFormat
     * @param stationDataList 站点数据
     * @return
     * @throws ParseException
     */
    private static List<StationData> sortByDate(SimpleDateFormat sdf, List<StationData> stationDataList) throws ParseException {
        StationData[] stationDataArray = stationDataList.toArray(new StationData[0]);
        for (int i = 0; i < stationDataArray.length; i++) {
            for (int j = i; j < stationDataArray.length; j++) {
                if (sdf.parse(stationDataArray[j].getDate()).before(sdf.parse(stationDataArray[i].getDate()))) {
                    StationData tmp = stationDataArray[j];
                    stationDataArray[j] = stationDataArray[i];
                    stationDataArray[i] = tmp;
                }
            }
        }
        return Arrays.asList(stationDataArray);
    }

    private static void assistHeader(List<String> result) {
        String head = "stationId,date,value";
        String type = "String,String,Double";
        result.add(head);
        result.add(type);
    }
}
